package ast2

import (
	"fmt"
	"strings"

	"gitee.com/u-language/u-language/ucom/astdata"
	"gitee.com/u-language/u-language/ucom/enum"
	"gitee.com/u-language/u-language/ucom/errcode"
	"gitee.com/u-language/u-language/ucom/internal/utils"
	"gitee.com/u-language/u-language/ucom/lex2"
)

// 有测试依赖函数体外的非声明语句，设置为true可以恢复之前的行为
// 缩写 Non declarative statements outside of a function 缩写成NdSotf
var NdSotfOn = false

func (t *Tree) Parser() {
	defer func() {
		if err := recover(); err != nil {
			if err != "exit" {
				panic(err)
			}
		}
	}()
	t.parserPackage()
	for tk := t.lex.Next(); tk.TYPE != lex2.EOF; tk = t.lex.Next() {
		t.parser(tk)
	}
}

func (t *Tree) parser(tk lex2.Token) (next lex2.Token) {
	switch tk.TYPE {
	case lex2.Package:
		t.panic(nil, errcode.PackageDeclMustFirstLine)
	case lex2.NewLine, lex2.MLC:
	case lex2.VAR:
		t.parserVar()
	case lex2.FUNC:
		t.parserFunc()
	case lex2.Return:
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserReturn()
	case lex2.NAME: //这里可能是自操作语句，赋值语句，函数调用
		if t.Funcinfo == nil && !NdSotfOn {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		n, next := t.parserStmt(tk, errcode.NoErr)
		t.shouldGot(next, lex2.NewLine, lex2.EOF)
		t.Nodes = append(t.Nodes, n)
	case lex2.RBRACE:
		t.SubRbrace()
		t.Nodes = append(t.Nodes, RbraceNode{})
		return tk
	case lex2.IF:
		if t.Funcinfo == nil && !NdSotfOn {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		return t.parserIf()
	case lex2.FOR:
		if t.Funcinfo == nil && !NdSotfOn {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserFor()
	case lex2.Struct:
		t.parserStruct()
	case lex2.Deref:
		if t.Funcinfo == nil && !NdSotfOn {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		n, next := t.parserStmt(tk, errcode.NoErr)
		t.shouldGot(next, lex2.NewLine, lex2.EOF)
		t.Nodes = append(t.Nodes, n)
	case lex2.Const:
		t.parserConst()
	case lex2.Switch:
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserSwitch()
	case lex2.Default:
		if !t.inSwitch.Get() {
			t.panicAndContinue(nil, errcode.DefaultErr, errcode.DefaultStmtInSwitch)
		}
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserDefault()
	case lex2.Break:
		if !t.inFor.Get() && !t.inSwitch.Get() {
			t.panicAndContinue(nil, errcode.BreakStmtInForOrSwitch)
		}
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.shouldGot(t.lex.Next(), lex2.NewLine)
		t.Nodes = append(t.Nodes, BreakStmt{})
	case lex2.Continue:
		if !t.inFor.Get() {
			t.panicAndContinue(nil, errcode.ContinueStmtInFor)
		}
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.shouldGot(t.lex.Next(), lex2.NewLine)
		t.Nodes = append(t.Nodes, ContinueStmt{})
	case lex2.Case:
		if !t.inSwitch.Get() {
			t.panicAndContinue(nil, errcode.CaseErr, errcode.CaseStmtInSwitch)
		}
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserCase()
	case lex2.Method:
		t.parserMethod()
	case lex2.AutoFree:
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserAutoFree()
	case lex2.Enum:
		t.parserEnum()
	case lex2.GOTO:
		if t.Funcinfo == nil {
			t.panicAndContinue(nil, errcode.NdSotf)
		}
		t.parserGoto()
	case lex2.Import:
		t.parserImport()
	default:
		t.unExpected(tk)
	}
	return
}

func (t *Tree) SubRbrace() {
	t.leftNum--
	if t.leftNum == 0 {
		t.Funcinfo = nil
		for i := range t.CheckInfo.Goto {
			if j := index(t.CheckInfo.Label, t.CheckInfo.Goto[i].Label); j == -1 {
				t.Panic(t.CheckInfo.Goto[i].LineNum, errcode.NewMsgLabelNoExist(t.CheckInfo.Goto[i].Label), errcode.GotoErr)
			}
		}
		t.CheckInfo.Label = t.CheckInfo.Label[0:0:cap(t.CheckInfo.Label)]
		t.CheckInfo.Goto = t.CheckInfo.Goto[0:0:cap(t.CheckInfo.Goto)]
	} else if t.leftNum < 0 {
		t.unExpected(lex2.NewToken(lex2.RBRACE, "}"))
	}
	t.originalSbtIndex--
	ori := t.originalSbt[t.originalSbtIndex]
	t.Sbt = ori
}

func index(s []*LabelNode, str string) int {
	for i := range s {
		if s[i].Value == str {
			return i
		}
	}
	return -1
}

func (t *Tree) parserPackage() {
	first := t.lex.Next()
	if first.TYPE != lex2.Package {
		t.subline(first)
		t.panic(nil, errcode.PackageDeclMustFirstLine)
	}
	packageName := t.lex.Next()
	t.shouldToken2(packageName, "package name", errcode.NoErr, lex2.NAME)
	if packageName.Value == "unsafe" {
		t.panic(nil, errcode.PackageNameCannotBeEqualUnsafe)
	}
	newline := t.lex.Next()
	t.shouldToken2(newline, "换行", errcode.NoErr, lex2.NewLine, lex2.EOF)
	t.PackageName = packageName.Value
}

// parserVar 尝试从Token中分析出一个变量声明
// 假设前一个Token是var
func (t *Tree) parserVar() {
	t.Nodes = append(t.Nodes, t.parserVar2(false))
}

func (t *Tree) parserVar2(inforstmt bool) *VarNode {
	name := t.lex.Next()
	t.shouldToken2(name, varname, errcode.VARErr, lex2.NAME)
	n := NewVarNode(name.Value, t.Funcinfo != nil, t.lex.Line)
	t.Sbt.AddVar(n)
	var tk lex2.Token
	n.TYPE, tk = t.parserType(errcode.VARErr)
	if t.Funcinfo == nil {
		//记录全局变量，用于生成C头文件
		t.CHeaderFile.Add(n)
	}
	if tk.TYPE == lex2.NewLine || tk.TYPE == lex2.EOF {
		return n
	}
	if t.Funcinfo == nil {
		//记录全局变量初始化，用于生成变量初始化顺序
		t.VarInitTable.Add(n)
	}
	t.shouldToken(tk, lex2.ASSIGN, errcode.VARErr)
	var next lex2.Token
	n.Value, next = t.parserExpr(errcode.VARErr, false)
	if inforstmt {
		t.shouldGot(next, lex2.SEMICOLON)
	} else {
		t.shouldGot(next, lex2.NewLine, lex2.EOF)
	}
	return n
}

// parserConst 尝试从Token中分析出一个常量声明
// 假设前一个Token是const
func (t *Tree) parserConst() {
	name := t.lex.Next()
	t.shouldToken2(name, constname, errcode.ConstErr, lex2.NAME)
	n := newConstNode(name.Value, t.lex.Line)
	t.Sbt.AddConst(n)
	var tk lex2.Token
	n.TYPE, tk = t.parserType(errcode.ConstErr)
	if tk.TYPE == lex2.NewLine || tk.TYPE == lex2.EOF {
		t.Nodes = append(t.Nodes, n)
		return
	}
	t.shouldToken(tk, lex2.ASSIGN, errcode.ConstErr)
	var next lex2.Token
	n.Value, next = t.parserExpr(errcode.ConstErr, false)
	t.shouldGot(next, lex2.NewLine, lex2.EOF)
	if t.Funcinfo == nil {
		t.CHeaderFile.Add(n)
	}
	t.Nodes = append(t.Nodes, n)
}

// parserType 解析一个类型
func (t *Tree) parserType(err errcode.ErrCode) (typ astdata.Typ, next lex2.Token) {
	tk := t.lex.Next()
	return t.parserType2(tk, err)
}

// parserType 在已经有一个Token的情况下解析一个类型
func (t *Tree) parserType2(oldtk lex2.Token, err errcode.ErrCode) (typ astdata.Typ, next lex2.Token) {
	switch oldtk.TYPE {
	case lex2.NAME:
		typ, next = t.parserSymbol(oldtk, err)
		if next.TYPE != lex2.LBRACK {
			typ.SetTyp()
			return typ, next
		}
		return t.parserGenericInstantiation(typ)
	case lex2.LEA:
		ret, next := t.parserLea(err)
		ret.SetTyp()
		return ret, next
	case lex2.LBRACK:
		ret, next := t.parserArray(err)
		return ret, next
	}
	t.unExpected(oldtk, err)
	return nil, t.lex.Next()
}

// parserExpr 尝试从Token中分析出一个表达式
func (t *Tree) parserExpr(err errcode.ErrCode, inCall bool) (expr Expr, next lex2.Token) {
	return t.parserExpr2(t.lex.Next(), err, inCall)
}

// parserExpr2 尝试从Token中分析出一个表达式
func (t *Tree) parserExpr2(tk lex2.Token, err errcode.ErrCode, inCall bool) (expr Expr, next lex2.Token) {
	if tk.TYPE == lex2.LEA { //看到&可以直接解析为取地址
		return t.parserLea(err)
	} else if tk.TYPE == lex2.RPAREN { //如果看到)，可能是没有参数的函数调用
		return nil, tk
	}
	s := newstack(false, inCall)
	s.err = err
	defer s.Close()
	return s.AutoExprNode(t, tk)
}

// parserLea 解析一个取地址
// 假设前一个Token是&
func (t *Tree) parserLea(err errcode.ErrCode) (ret interface {
	Expr
	astdata.Typ
}, next lex2.Token) {
	obj := &Object{Kind: LeaObj}
	src := t.lex.Next()
	if src.TYPE != lex2.NAME {
		t.unExpected(src, err)
	}
	obj.Name = src.Value
	next = t.lex.Next()
	if next.TYPE == lex2.PERIOD { //如果是&symbol.这样的选择器
		return t.parserSelect2(*obj, err)
	}
	return obj, next
}

// parserDeref 解析一个解引用
// 假设前一个Token是@
func (t *Tree) parserDeref(err errcode.ErrCode, src lex2.Token) (ret Expr, next lex2.Token) {
	var obj = &Object{Kind: DerefObj}
	if src.TYPE == lex2.LPAREN {
		ret := &DerefExpr{}
		ret.LineNum = t.lex.Line
		//TODO:为了把)视为表达式结束的标志，所以把t.parserExpr的第二个参数iscall设为true,这个参数名未来需要修正
		expr, next := t.parserExpr(err, true)
		t.shouldGot(next, lex2.RPAREN)
		ret.Value = expr
		return ret, t.lex.Next()
	} else if src.TYPE != lex2.NAME {
		t.unExpected(src, err)
	}
	next = t.lex.Next()
	obj.Name = src.Value
	if next.TYPE == lex2.PERIOD { //如果是@symbol.这样的选择器
		return t.parserSelect2(*obj, err)
	}
	return obj, next
}

// parserObject 尝试解析一个对象，如有可能，会解析出选择器
func (t *Tree) parserObject(tk lex2.Token, err errcode.ErrCode) (ret Expr, next lex2.Token) {
	return t.parserObject2(tk, t.lex.Next(), err)
}

// parserObject2 尝试解析一个对象，如有可能，会解析出选择器
func (t *Tree) parserObject2(tk, tk2 lex2.Token, err errcode.ErrCode) (ret Expr, next lex2.Token) {
	obj := &Object{}
	switch tk.TYPE {
	case lex2.NAME:
		obj.Kind = SymbolObj
	case lex2.Nil:
		obj.Kind = NilObj
	case lex2.Int:
		obj.Kind = INTOBJ
	case lex2.FLOAT:
		obj.Kind = FLOATOBJ
	case lex2.String:
		obj.Kind = StringObj
	case lex2.TRUE, lex2.FALSE:
		obj.Kind = BoolObj
	case lex2.Deref:
		return t.parserDeref(err, tk2)
	default:
		t.subline(tk2)
		t.unExpected(tk, err)
	}
	obj.Name = tk.Value
	return obj, tk2
}

func (t *Tree) parserFunc() {
	info := t.parserFuncInfo("func name", errcode.FUNCErr)
	var init bool
	if info.Name == "init" {
		init = true
		info.Name = utils.GeneratePackageSymbol(t.PackageName, "init__user")
	}
	t.Funcinfo = info
	//创建函数节点
	f := NewFuncNode(info)
	f.Sbt.seniorSbt(t.Sbt)
	//记录函数节点
	err := t.Sbt.AddFunc(f)
	if err != errcode.NoErr {
		//TODO:报错
		return
	}
	//设置新当前代码块符号表
	t.PushNewSbt(f.Sbt)
	t.CHeaderFile.Add(f)
	t.Nodes = append(t.Nodes, f)
	if info.Name == "main" {
		if len(info.RetValue) != 0 {
			t.panic(nil, errcode.MainNoRetValue)
		}
		info.RetValue = append(info.RetValue, astdata.NewNameAndType("", NewObject(TypeObj, "int")))
	} else if init {
		*t.HaveInitFunc = true
	}
	t.parserCodeBlock()
}

func (t *Tree) parserFuncInfo(nameErr string, err errcode.ErrCode) *FuncInfo {
	ret := &FuncInfo{}
	ret.codeBlock = newCodeBlock(t.lex.Line)
	name := t.lex.Next()
	ret.Name = name.Value
	t.shouldToken2(name, nameErr, err, lex2.NAME)
	start := t.lex.Next()
	if start.TYPE == lex2.LBRACK {
		ret.TypeParame = t.parserTypeParame(err)
		start = t.lex.Next()
	}
	t.shouldToken2(start, "(", err, lex2.LPAREN)
	ret.Parame, ret.RetValue = t.parserFuncParameAndRet()
	for i := range ret.Parame {
		v := NewVarNode(ret.Parame[i].Name, true, ret.LineNum)
		v.TYPE = ret.Parame[i].Type
		ret.Sbt.AddVar(v)
	}
	return ret
}

func (t *Tree) parserFuncParameAndRet() ([]astdata.Parame, []astdata.RetValue) {
	var (
		name     string
		typ      astdata.Typ
		comma    = 0
		parame   []astdata.Parame
		retvalue []astdata.RetValue = nil
	)
loop:
	for tk := t.lex.Next(); ; {
		switch tk.TYPE {
		case lex2.RPAREN:
			break loop
		case lex2.NAME:
			comma = 0
			name = tk.Value
			typ, tk = t.parserType(errcode.FUNCErr)
			parame = append(parame, astdata.Parame{Name: name, Type: typ})
		case lex2.Comma:
			comma++
			if comma != 1 { //如果不止一个逗号相邻
				t.unExpected(tk, errcode.FUNCErr)
			}
			tk = t.lex.Next()
		default:
			t.unExpected(tk, errcode.FUNCErr)
		}
	}
	tk := t.lex.Next()
	if tk.TYPE == lex2.LBRACE { //如果没有返回值
		return parame, retvalue
	}
	//如果有返回值
	typ, tk = t.parserType2(tk, errcode.FUNCErr)
	retvalue = append(retvalue, astdata.RetValue{Name: "", Type: typ})
	t.shouldToken2(tk, "{", errcode.FUNCErr, lex2.LBRACE)
	return parame, retvalue
}

func (t *Tree) parserReturn() {
	ret := &ReturnNode{}
	ret.LineNum = t.lex.Line
	tk := t.lex.Next()
	if tk.TYPE == lex2.NewLine {
		t.Nodes = append(t.Nodes, ret)
		return
	}
	var next lex2.Token
	ret.RetValue, next = t.parserExpr2(tk, errcode.ReturnErr, false)
	//Note:返回语句后不应该是EOF，因为返回语句应该在函数内，函数应该以右大括号结束
	//例如解析这样的代码应该报错
	//func a()int{
	// return 1
	t.shouldGot(next, lex2.NewLine)
	t.Nodes = append(t.Nodes, ret)
}

// parserStmt 尝试从Token中分析出一个语句
// 假设 start 表示一个符号
func (t *Tree) parserStmt(start lex2.Token, err errcode.ErrCode) (n Node, next lex2.Token) {
	dest, next := t.parserSymbol(start, err)
	switch next.TYPE {
	case lex2.NewLine:
		t.lex.Line--
		t.unExpected(start)
		return dest, t.lex.Next()
	case lex2.EOF:
		t.lex.Line--
		t.unExpected(start)
		return dest, t.lex.Next()
	case lex2.Inc:
		n = newSelfOpStmt(enum.IncOP, dest, t.lex.Line)
		next = t.lex.Next()
	case lex2.Dec:
		n = newSelfOpStmt(enum.DecOP, dest, t.lex.Line)
		next = t.lex.Next()
	case lex2.LPAREN: //推测是函数调用
		line := t.lex.Line
		n, next = t.parserCall2(dest, t.lex.Next(), line)
	case lex2.ASSIGN: //推测是赋值
		assign := NewASSIGNNode(dest, nil, t.lex.Line)
		next = t.lex.Next()
		assign.Src, next = t.parserExpr2(next, errcode.ASSIGNErr, false)
		n = assign
	case lex2.LBRACK: //如果是[,推测为下标表达式
		var i Expr
		line := t.lex.Line
		next = t.lex.Next()
		i, next = t.parserIndexExprOrGenericInstantiation(dest, next, line)
		if next.TYPE == lex2.ASSIGN {
			assign := NewASSIGNNode(i, nil, t.lex.Line)
			assign.Src, next = t.parserExpr(errcode.ASSIGNErr, false)
			n = assign
		} else {
			t.unExpected(next, err)
		}
	case lex2.Colon:
		o, ok := dest.(*Object)
		if !ok {
			t.panic(nil, errcode.LabelErr, errcode.OPbug)
		}
		return NewLabelNode(o.Name, t.lex.Line), t.lex.Next()
	default:
		t.unExpected(next, err)
	}
	return
}

// parserSelect 解析一个选择器
func (t *Tree) parserSelect(start lex2.Token, err errcode.ErrCode) (ret *Objects, next lex2.Token) {
	obj := t.parserObject3(start, err, true)
	return t.parserSelect2(obj, err)
}

// parserSelect2 从解析的开头开始解析选择器
func (t *Tree) parserSelect2(start Object, err errcode.ErrCode) (ret *Objects, next lex2.Token) {
	ret = new(Objects)
	ret.Slice = append(ret.Slice, start)
	next = t.lex.Next()
	for {
		obj := t.parserObject3(next, err, false)
		ret.Slice = append(ret.Slice, obj)
		next = t.lex.Next()
		if next.TYPE != lex2.PERIOD {
			return
		}
		next = t.lex.Next()
	}
}

// parserObject3 尝试解析一个对象，直解析单Token符号或&或@跟着单Token符号
func (t *Tree) parserObject3(tk lex2.Token, err errcode.ErrCode, acceptDeref bool) (ret Object) {
	obj := Object{}
	switch tk.TYPE {
	case lex2.NAME:
		obj.Kind = SymbolObj
	case lex2.Nil:
		obj.Kind = NilObj
	case lex2.Int:
		obj.Kind = INTOBJ
	case lex2.FLOAT:
		obj.Kind = FLOATOBJ
	case lex2.String:
		obj.Kind = StringObj
	case lex2.TRUE, lex2.FALSE:
		obj.Kind = BoolObj
	case lex2.Deref:
		if !acceptDeref {
			t.unExpected(tk, err)
		}
		next := t.lex.Next()
		if next.TYPE == lex2.NAME {
			obj.Kind = DerefObj
			obj.Name = tk.Value
			return
		}
		t.unExpected(next)
	default:
		t.unExpected(tk, err)
	}
	obj.Name = tk.Value
	return obj
}

// parserIf 解析一个if
// 假设前一个Token是if
func (t *Tree) parserIf() (next lex2.Token) {
	n := NewIfNode(t.lex.Line)
	n.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(n.Sbt)
	boolexpr, next := t.parserExpr(errcode.IfErr, false)
	t.shouldGot(next, lex2.LBRACE)
	n.BoolExpr = boolexpr
	t.Nodes = append(t.Nodes, n)
	t.parserCodeBlock()
	return t.findElse()
}

func (t *Tree) parserCodeBlock() {
	for tk := t.lex.Next(); ; tk = t.lex.Next() { //解析代码块内的语句
		next := t.parser(tk)
		if next.TYPE == lex2.RBRACE {
			break
		}
	}
}

// 这个函数返回的token只可能是}或空
func (t *Tree) findElse() (next lex2.Token) {
	next = t.lex.Next()
	//支持 if {...} else 和 if {...} newline else 或 else if {...} else 和 else if {...} newline else
	if next.TYPE == lex2.ELSE {
		return t.parserElse()
	} else if next.TYPE == lex2.NewLine {
		next = t.lex.Next()
		if next.TYPE == lex2.RBRACE {
			//如果代码是
			//if cond{
			//	if cond2{
			//
			//	}
			//} <--此时解析到这
			// 或是
			//if cond{
			//	else {
			//
			//	}
			//}
			//或其他在if或else语句这种条件判断语句，结束后有换行后面跟着},都选择返回},以避免条件判断语句嵌套时外层的语句看不到标志着它结束的}
			t.SubRbrace()
			t.Nodes = append(t.Nodes, NewRbraceNode())
			return next
		}
		if next.TYPE == lex2.ELSE {
			return t.parserElse()
		}
		if next.TYPE == lex2.IF {
			return t.parser(next)
		}
		return t.parser(next)
	} else if next.TYPE == lex2.EOF {
	} else {
		t.unExpected(next)
	}
	return lex2.Token{}
}

// parserElse 解析一个else 或 else if
// 假设前一个Token是else
func (t *Tree) parserElse() (next lex2.Token) {
	n := NewElseNode(t.lex.Line)
	n.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(n.Sbt)
	after := t.lex.Next()
	if after.TYPE == lex2.IF { //如果是else if
		n.BoolExpr, next = t.parserExpr(errcode.ElseErr, false)
		if n.BoolExpr == nil {
			t.panic(nil, errcode.ElseErr, errcode.NoBoolExpr)
		}
	} else {
		next = after
	}
	t.shouldGot(next, lex2.LBRACE)
	t.Nodes = append(t.Nodes, n)
	t.parserCodeBlock()
	return t.findElse()
}

// parserSymbol 解析一个标识符
// 标识符可能是object
// 也可能是选择器
func (t *Tree) parserSymbol(start lex2.Token, err errcode.ErrCode) (ret interface {
	Expr
	astdata.Typ
}, next lex2.Token) {
	tk, tk2 := start, t.lex.Next()
	if tk2.TYPE == lex2.PERIOD {
		return t.parserSelect(tk, err)
	}
	o, next := t.parserObject2(tk, tk2, err)
	typ, ok := o.(interface {
		Expr
		astdata.Typ
	})
	if !ok {
		t.panic(nil, err, errcode.OPbug)
	}
	return typ, next
}

// parserCall2 在解析好函数名的基础上解析一个函数调用
func (t *Tree) parserCall2(nameNode Expr, next lex2.Token, LineNum int) (*CallNode, lex2.Token) {
	n := NewCallExpr(nameNode, LineNum)
	comma := 0
	rparen := false
	var expr Expr
loop:
	for {
		expr, next = t.parserExpr2(next, errcode.CallErr, true)
		if expr != nil {
			n.Parame = append(n.Parame, expr)
		}
		switch next.TYPE {
		case lex2.RPAREN:
			rparen = true
			fallthrough
		case lex2.NewLine, lex2.EOF:
			break loop
		case lex2.Comma:
			comma++
			if comma != len(n.Parame) { //如果有多个逗号连在一起
				t.panic(errcode.NewMsgUnexpected(next.Value), errcode.CallErr)
			}
			next = t.lex.Next()
			continue
		default:
			t.unExpected(next, errcode.CallErr)
		}
	}
	if !rparen {
		t.unExpected(next, errcode.CallErr)
	}
	return n, t.lex.Next()
}

// parserFor 解析一个for
// 假设前一个Token是for
func (t *Tree) parserFor() {
	forstmt := NewForNode(t.lex.Line)
	forstmt.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(forstmt.Sbt)
	init, boolexpr, next := t.parserForInitStmt(), t.parserForBoolStmt(), t.parserForEndStmt()
	forstmt.InitStmt, forstmt.BoolExpr, forstmt.EndStmt = init, boolexpr, next
	t.Nodes = append(t.Nodes, forstmt)
	t.inFor.Push()
	t.parserCodeBlock()
	t.inFor.Pop()
}

// parserInitStmt 解析一个for初始化语句
// 假设前一个Token是for
func (t *Tree) parserForInitStmt() Node {
	tk := t.lex.Next()
	switch tk.TYPE {
	case lex2.VAR:
		return t.parserVar2(true)
	case lex2.SEMICOLON:
	default:
		t.unExpected(tk, errcode.ForErr)
	}
	return nil
}

// parserBoolStmt 解析一个for布尔表达式
// 假设前一个Token是;
func (t *Tree) parserForBoolStmt() Expr {
	tk := t.lex.Next()
	switch tk.TYPE {
	case lex2.SEMICOLON:
	default:
		ret, next := t.parserExpr2(tk, errcode.ForErr, false)
		if o, ok := ret.(set_nosemicolon_interface); ok {
			o.SetNosemicolon(true)
		}
		t.shouldGot(next, lex2.SEMICOLON)
		return ret
	}
	return nil
}

// parserEndStmt 解析一个for结束语句
// 假设前一个Token是;
func (t *Tree) parserForEndStmt() Node {
	tk := t.lex.Next()
	switch tk.TYPE {
	case lex2.LBRACE:
	default:
		ret, next := t.parserStmt(tk, errcode.ForErr)
		if o, ok := ret.(set_nosemicolon_interface); ok {
			o.SetNosemicolon(true)
		}
		t.shouldGot(next, lex2.LBRACE)
		return ret
	}
	return nil
}

// parserTypeParame 解析类型参数列表
func (t *Tree) parserTypeParame(err errcode.ErrCode) (ret []astdata.NameAndType) {
	for {
		name := t.lex.Next()
		t.shouldGot(name, lex2.NAME)
		constraint, next := t.parserType(err)
		ret = append(ret, astdata.NewNameAndType(name.Value, constraint))
		if next.TYPE == lex2.Comma {
			continue
		}
		if next.TYPE != lex2.RBRACK {
			t.unExpected(next, err)
		}
		return
	}
}

// parserStruct 解析一个结构体声明
// 假设前一个Token是struct
func (t *Tree) parserStruct() {
	var s = &StructDecl{}
	s.InFunc = t.Funcinfo != nil
	s.LineNum = t.lex.Line
	name := t.lex.Next()
	t.shouldToken2(name, "结构体名", errcode.StructErr, lex2.NAME)
	next := t.lex.Next()
	if next.TYPE == lex2.LBRACK {
		s.TypeParame = t.parserTypeParame(errcode.StructErr)
		next = t.lex.Next()
	}
	t.shouldToken2(next, "左大括号", errcode.StructErr, lex2.LBRACE)
	t.PushNewSbt(t.Sbt)
	t.shouldNext("换行", lex2.NewLine)
	s.Name = name.Value
	s.FieldTable = t.parserStructField()
	t.Sbt.AddStruct(s)
	if t.Funcinfo == nil {
		t.CHeaderFile.Add(s)
	}
	t.Nodes = append(t.Nodes, s)
}

func (t *Tree) parserStructField() (ret []astdata.NameAndType) {
	var next lex2.Token
	for {
		tk := t.lex.Next()
		if tk.TYPE == lex2.RBRACE { //如果是右大括号，视为结构体结束
			t.SubRbrace()
			return
		}
		if tk.TYPE != lex2.NAME {
			if next.TYPE == lex2.NewLine {
				t.lex.Line--
			}
			t.expectedAndFound("结构体字段名或}", tk, errcode.StructErr)
		}
		typ, next := t.parserType(errcode.StructErr)
		ret = append(ret, astdata.NewNameAndType(tk.Value, typ))
		if next.TYPE != lex2.NewLine { //如果不是正确的字段语法 name type Newline 报错
			t.unExpected(next, errcode.StructErr)
		}
	}
}

// parserSwitch 解析一个switch语句
// 假设前一个Token是switch
func (t *Tree) parserSwitch() {
	s := NewSwitchNode(t.lex.Line)
	s.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(s.Sbt)
	expr, next := t.parserExpr(errcode.SwitchErr, false)
	s.Expr = expr
	t.shouldToken2(next, "{", errcode.SwitchErr, lex2.LBRACE)
	t.Nodes = append(t.Nodes, s)
	t.inSwitch.Push()
	t.parserCodeBlock()
	t.inSwitch.Pop()
}

// parserDefault 解析一个default语句
// 假设前一个Token是default
func (t *Tree) parserDefault() {
	t.shouldNext(":", lex2.Colon)
	n := NewDefaultNode(t.lex.Line)
	n.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(n.Sbt)
	t.Nodes = append(t.Nodes, n)
}

// parserCase 解析一个case语句
// 假设前一个Token是case
func (t *Tree) parserCase() {
	c := NewCaseNode(t.lex.Line)
	c.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(c.Sbt)
	expr, next := t.parserExpr(errcode.CaseErr, false)
	c.Expr = expr
	t.shouldToken2(next, ":", errcode.CaseErr, lex2.Colon)
	t.Nodes = append(t.Nodes, c)
}

// parserMethod 解析一个方法声明
// 假设前一个Token是method
func (t *Tree) parserMethod() {
	info := t.parserFuncInfo("method name", errcode.MethodErr)
	n := NewMethodNode(info)
	n.Sbt.seniorSbt(t.Sbt)
	t.Sbt.AddMethod(n)
	t.PushNewSbt(n.Sbt)
	if t.Funcinfo == nil {
		t.CHeaderFile.Add(n)
	}
	t.Funcinfo = info
	t.Nodes = append(t.Nodes, n)
	t.parserCodeBlock()
}

// parserAutoFree 解析一个自动释放块
// 假设前一个Token是autofree
func (t *Tree) parserAutoFree() {
	n := NewAutoFreeNode(t.Filename, t.lex.Line)
	n.Sbt.seniorSbt(t.Sbt)
	t.PushNewSbt(n.Sbt)
	expr, next := t.parserExpr(errcode.AutoFreeErr, false)
	n.Expr = expr
	t.shouldToken2(next, "{", errcode.AutoFreeErr, lex2.LBRACE)
	t.Nodes = append(t.Nodes, n)
	t.parserCodeBlock()
}

// parserArray 解析一个数组类型
// 左右的中括号是必须有左右中括号的意思
func (t *Tree) parserArray(err errcode.ErrCode) (ret *Array, next lex2.Token) {
	a := &Array{sbt: t.Sbt, LineNum: t.lex.Line}
	len, next := t.parserExpr(err, false)
	t.shouldGot(next, lex2.RBRACK)
	typ, next := t.parserType(err)
	a.Len, a.TYPE = len, typ
	return a, next
}

func (t *Tree) parserIndexExprOrGenericInstantiation(start Expr, after lex2.Token, LineNum int) (ret Expr, nextl lex2.Token) {
	first, nextl := t.parserSymbol(after, errcode.NoErr)
	if nextl.TYPE == lex2.RBRACK {
		//Note:如果是symbol[symbol],这种情况可能是泛型实例化，也可能是获取数组元素，先解析为索引表达式，等待语义检查再根据类型信息判断是哪种情况
		ret := NewIndexExpr(start, LineNum)
		ret.Index = first
		nextl = t.lex.Next()
		if nextl.TYPE == lex2.LBRACK { //如果可能是x[expr][expr]
			return t.parserIndexExpr(ret)
		}
		return ret, nextl
	} else if nextl.TYPE == lex2.Comma {
		base, ok := start.(astdata.Typ)
		if !ok {
			t.panic(nil, errcode.OPbug)
		}
		return t.parserGenericInstantiation2(base, first)
	}
	i := NewIndexExpr(start, LineNum)
	s := newstack(false, false)
	s.PushValue(first, t)
	i.Index, nextl = s.AutoExprNode(t, nextl)
	ret = i
	s.Close()
	if nextl.TYPE != lex2.RBRACK { //如果不是x[expr]
		t.unExpected(nextl)
	}
	nextl = t.lex.Next()
	if nextl.TYPE != lex2.LBRACK { //如果不是x[expr][expr]
		return ret, nextl
	}
	return t.parserIndexExpr(i)
}

func (t *Tree) parserIndexExpr(start Expr) (Expr, lex2.Token) {
	var nextl = t.lex.Next()
	for {
		i := &IndexExpr{X: start}
		i.Index, nextl = t.parserExpr2(nextl, errcode.NoErr, false)
		t.shouldGot(nextl, lex2.RBRACK)
		nextl = t.lex.Next()
		if nextl.TYPE == lex2.LBRACK { //如果可能是x[expr][expr]
			start = i
			nextl = t.lex.Next()
			continue
		}
		return i, nextl
	}
}

// parserEnum 解析一个枚举声明
// 假设前一个Token是enum
func (t *Tree) parserEnum() {
	name := t.lex.Next()
	t.shouldGot(name, lex2.NAME)
	e := NewEnumDecl(name.Value, t.lex.Line, t.Funcinfo != nil)
	t.shouldToken2(t.lex.Next(), "{", errcode.EnumErr, lex2.LBRACE)
	t.PushNewSbt(t.Sbt)
	t.shouldGot(t.lex.Next(), lex2.NewLine)
	e.Enums = t.parserEnumValue()
	t.Sbt.AddEnum(e)
	if t.Funcinfo == nil {
		t.CHeaderFile.Add(e)
	}
	for i := 0; i < len(e.Enums); i++ { //重写标识符
		var buf strings.Builder
		// buf.WriteString(t.PackageName)
		// buf.WriteString(enum.PackageSep)
		buf.WriteString(e.Name)
		buf.WriteString(enum.PackageSep)
		buf.WriteString(e.Enums[i])
		e.Enums[i] = buf.String()
	}
	t.Nodes = append(t.Nodes, e)
}

func (t *Tree) parserEnumValue() (ret []string) {
	for {
		v := t.lex.Next()
		if v.TYPE == lex2.RBRACE {
			t.SubRbrace()
			return
		}
		if v.TYPE != lex2.NAME {
			t.panic(errcode.NewMsgUnexpected(t.lex2TokenToStr(v)), errcode.EnumErr, errcode.EnumValueShouldBeASymbol)
		}
		ret = append(ret, v.Value)
		next := t.lex.Next()
		if next.TYPE == lex2.NewLine {
			continue
		}
		t.panic(errcode.NewMsgUnexpected(t.lex2TokenToStr(v)), errcode.EnumErr, errcode.EnumValueShouldHaveOneOnEachLine)
	}
}

// parserGoto 解析一个goto语句
func (t *Tree) parserGoto() {
	s := NewGotoStmt(t.lex.Line)
	label := t.lex.Next()
	if label.TYPE != lex2.NAME {
		t.panic(errcode.NewMsgUnexpected(t.lex2TokenToStr(label)), errcode.GotoErr, errcode.NoLabel)
	}
	s.Label = label.Value
	t.Nodes = append(t.Nodes, s)
}

// parserGenericInstantiation 解析一个泛型实例化
func (t *Tree) parserGenericInstantiation(base astdata.Typ) (ret *GenericInstantiation, next lex2.Token) {
	first, next := t.parserSymbol(t.lex.Next(), errcode.NoErr)
	if next.TYPE == lex2.RBRACK {
		//Note:如果是s[symbol],这种情况可能是泛型实例化，也可能是获取数组元素，因为这里是在解析类型，所以判断为泛型实例化
		return &GenericInstantiation{BaseName: base, ActualType: []astdata.Typ{first}}, t.lex.Next()
	} else if next.TYPE == lex2.Comma {
		return t.parserGenericInstantiation2(base, first)
	}
	t.unExpected(next)
	return nil, t.lex.Next()
}

// parserGenericInstantiation2 解析一个泛型实例化
func (t *Tree) parserGenericInstantiation2(base astdata.Typ, first astdata.Typ) (ret *GenericInstantiation, next lex2.Token) {
	ret = new(GenericInstantiation)
	ret.BaseName = base
	ret.ActualType = append(ret.ActualType, first)
	var typ astdata.Typ
	next = t.lex.Next()
	for {
		typ, next = t.parserType2(next, errcode.NoErr)
		ret.ActualType = append(ret.ActualType, typ)
		if next.TYPE == lex2.Comma {
			continue
		}
		if next.TYPE == lex2.RBRACK || next.TYPE == lex2.NewLine || next.TYPE == lex2.EOF {
			next = t.lex.Next()
			return
		}
	}
}

var zero fmt.Stringer = &Tree{}

// parserImport 解析一个import块
func (t *Tree) parserImport() {
	t.shouldToken(t.lex.Next(), lex2.LBRACE, errcode.ImportErr)
	t.shouldToken(t.lex.Next(), lex2.NewLine, errcode.ImportErr)
	for tk := t.lex.Next(); ; tk = t.lex.Next() {
		if tk.TYPE == lex2.RBRACE {
			return
		}
		t.shouldGot(tk, lex2.String)
		t.ImporPath.add(tk.Value, zero)
		t.shouldToken(t.lex.Next(), lex2.NewLine, errcode.ImportErr)
	}
}

// shouldNext 判断后一个Token是不是指定类型的Token
func (t *Tree) shouldNext(wantstr string, want lex2.TokenType) {
	got := t.lex.Next()
	if got.TYPE != want {
		t.expectedAndFound(wantstr, got)
	}
}

// shouldGot 判断得到的Token是不是指定类型的Token
func (t *Tree) shouldGot(got lex2.Token, want ...lex2.TokenType) {
	for _, v := range want {
		if got.TYPE == v {
			return
		}
	}
	t.panic(errcode.NewMsgUnexpected(t.lex2TokenToStr(got)))
}

// shouldToken 判断是不是指定类型的Token，如果不是，报错
func (t *Tree) shouldToken(tk lex2.Token, want lex2.TokenType, err errcode.ErrCode) {
	if tk.TYPE != want {
		//TODO:改进报错，报告期望什么
		t.panic(errcode.NewMsgUnexpected(t.lex2TokenToStr(tk)), err)
	}
}

func (t *Tree) shouldToken2(tk lex2.Token, wantstr string, err errcode.ErrCode, want ...lex2.TokenType) {
	for _, v := range want {
		if tk.TYPE == v {
			return
		}
	}
	if err != errcode.NoErr {
		t.expectedAndFound(wantstr, tk, err)
	} else {
		t.expectedAndFound(wantstr, tk)
	}
}

func (t *Tree) expectedAndFound(want string, got lex2.Token, code ...errcode.ErrCode) {
	t.panic(errcode.NewMsgExpectedAndFound(want, t.lex2TokenToStr(got)), code...)
}

func (t *Tree) unExpected(tk lex2.Token, err ...errcode.ErrCode) {
	t.panic(errcode.NewMsgUnexpected(t.lex2TokenToStr(tk)), err...)
}

func (t *Tree) panic(msg errcode.Msg, code ...errcode.ErrCode) {
	t.panicAndContinue(msg, code...)
	panic("exit")
}

// panicAndContinue 报错但继续解析
func (t *Tree) panicAndContinue(msg errcode.Msg, code ...errcode.ErrCode) {
	if len(code) != 0 && code[0] == errcode.NoErr {
		if len(code) > 1 {
			code = code[1:]
		} else {
			code = nil
		}
	}
	t.errctx.Panic(t.Filename, t.lex.Line, msg, code...)
}

// 如果有错误但已经报告了使用这个值
var ignore = errcode.ErrCode(10000)

func (t *Tree) Panic(Line int, msg errcode.Msg, code ...errcode.ErrCode) {
	for i := range code {
		//有ignore,直接返回，因为已经报错过了
		if code[i] == ignore {
			return
		}
	}
	t.errctx.Panic(t.Filename, Line, msg, code...)
}

func (t *Tree) subline(tk lex2.Token) {
	if tk.TYPE == lex2.NewLine || (tk.TYPE == lex2.EOF && t.lex.EOFIsNewLine()) {

		t.lex.Line--
	}
}

func (t *Tree) lex2TokenToStr(tk lex2.Token) string {
	t.subline(tk)
	switch tk.TYPE {
	case lex2.EOF:
		return "文件结束"
	case lex2.NewLine:
		return "换行"
	}
	return tk.Value
}

func (t *Tree) PushNewSbt(sbt *Sbt) {
	t.leftNum++
	t.originalSbt = append(t.originalSbt[:t.originalSbtIndex], t.Sbt)
	t.originalSbtIndex++
	t.Sbt = sbt
}
